package logic

import (
	"context"
	"fmt"
	"github.com/elastic/go-elasticsearch/v8/esapi"

	"encoding/json"
	"lucky/es"
	"lucky/luckyrpc/internal/svc"
	"lucky/luckyrpc/luckyrpc"
	"lucky/models"
	"strings"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
)

type ProductListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ProductListLogic {
	return &ProductListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ProductListLogic) ProductList(in *luckyrpc.ProductListRequest) (*luckyrpc.ProductListResponse, error) {
	// todo: add your logic here and delete this line

	params := models.ProductSearchRequest{
		Name:     in.Name,
		Taste:    in.Taste,
		MaxPrice: float64(in.MaxPrice),
		MinPrice: float64(in.MinPrice),
		Page:     in.Page,
		Limit:    in.Limit,
		Sort:     in.Sort,
	}
	//if in.Name != "" {
	//	byES, err := l.ProductListByES(in)
	//	if err != nil {
	//		return nil, err
	//	}
	//	return &luckyrpc.ProductListResponse{
	//		Total: byES.Total,
	//		List:  byES.List,
	//	}, nil
	//}

	result := params.ProductSearch(models.DB)

	var products []*luckyrpc.ProductList

	for _, product := range result.Products {
		list := luckyrpc.ProductList{
			Name:       product.Name,
			Price:      float32(product.Price),
			Stock:      product.Stock,
			Ingredient: product.Ingredient,
			Taste:      product.Taste,
			Status:     product.Status,
			ImageUrl:   product.ImageUrl,
			Category:   product.Category,
			CreatedAt:  product.CreatedAt.Format(time.DateTime),
		}
		products = append(products, &list)
	}
	return &luckyrpc.ProductListResponse{
		Total: result.Total,
		List:  products,
	}, nil
}
func (l *ProductListLogic) ProductListByES(in *luckyrpc.ProductListRequest) (*luckyrpc.ProductListResponse, error) {

	if in.Page < 1 {
		in.Page = 1
	}
	if in.Limit < 10 {
		in.Limit = 10
	}
	if in.Limit > 100 {
		in.Limit = 100
	}

	form := (in.Page - 1) * in.Limit
	if form < 0 {
		form = 0
	}
	boolQuery := map[string]interface{}{
		"bool": map[string]interface{}{
			"must": []interface{}{
				map[string]interface{}{
					"match": map[string]interface{}{
						"name": map[string]interface{}{
							"query":     in.Name,
							"fuzziness": "AUTO",
						},
					},
				},
			},
			"filter": map[string]interface{}{},
		},
	}
	filters := boolQuery["bool"].(map[string]interface{})["filter"].([]interface{})

	if in.Taste != "" {
		filters = append(filters, map[string]interface{}{
			"term": map[string]interface{}{
				"taste。keyword": in.Taste,
			},
		})
	}
	var sortType []interface{}

	switch in.Sort {
	case "price_desc":
		sortType = append(sortType, map[string]interface{}{
			"price": map[string]interface{}{
				"order":   "desc",
				"missing": "_last", // 处理价格为空的商品，放最后
			},
		})
	case "price_asc":
		sortType = append(sortType, map[string]interface{}{
			"price": map[string]interface{}{
				"order":   "asc",
				"missing": "_last", // 处理价格为空的商品，放最后
			},
		})
	case "stock_desc":
		sortType = append(sortType, map[string]interface{}{
			"stock": map[string]interface{}{
				"order":   "desc",
				"missing": "_last", // 处理价格为空的商品，放最后
			},
		})
	case "stock_asc":
		sortType = append(sortType, map[string]interface{}{
			"stock": map[string]interface{}{
				"order":   "asc",
				"missing": "_last", // 处理价格为空的商品，放最后
			},
		})
	default:
		sortType = append(sortType, map[string]interface{}{
			"creat_at": map[string]interface{}{
				"order": "desc",
			},
		})
	}

	boolQuery["bool"].(map[string]interface{})["filter"] = filters

	query := map[string]interface{}{
		"query": boolQuery,
		"sort":  sortType,
		"form":  form,
		"limit": in.Limit,
	}

	jsonData, err := json.Marshal(query)
	if err != nil {
		return nil, fmt.Errorf("构建查询JSON失败: %v", err)
	}

	indexName := "luck_product"
	resp := esapi.SearchRequest{
		Index: []string{indexName},
		Body:  strings.NewReader(string(jsonData)),
	}
	do, err := resp.Do(context.Background(), es.ElasticSearchClient)
	if err != nil {
		return nil, fmt.Errorf("执行ES查询失败: %v", err)
	}
	defer do.Body.Close()

	if do.IsError() {
		var errResp map[string]interface{}
		err = json.NewDecoder(do.Body).Decode(&errResp)
		if err != nil {
			return nil, fmt.Errorf("ES返回错误，但解析失败: %v", err)
		}
		return nil, fmt.Errorf("ES查询错误: %v", errResp["error"])
	}

	var result map[string]interface{}
	err = json.NewDecoder(do.Body).Decode(&result)
	if err != nil {
		return nil, fmt.Errorf("解析ES结果失败: %v", err)
	}

	fmt.Println(result)

	hits, ok := result["hits"].(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("解析hits结构失败")
	}
	totalVal, ok := hits["total"].(map[string]interface{})["value"].(float64)
	if !ok {
		return nil, fmt.Errorf("解析总命中数失败")
	}
	total := int64(totalVal)

	// 解析商品列表
	var products []*luckyrpc.ProductList
	for _, hit := range hits["hits"].([]interface{}) {
		hitMap, ok := hit.(map[string]interface{})
		if !ok {
			continue
		}
		source, ok := hitMap["_source"].(map[string]interface{})
		if !ok {
			continue
		}
		jsonByte, err := json.Marshal(source)
		if err != nil {
			continue
		}
		var product luckyrpc.ProductList
		if err := json.Unmarshal(jsonByte, &product); err != nil {
			continue
		}
		products = append(products, &product)
	}
	return &luckyrpc.ProductListResponse{
		Total: total,
		List:  products,
	}, nil
}
